package controllers;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import notifiers.Mails;

import org.apache.commons.beanutils.BeanUtils;

import jxl.write.WriteException;
import models.ArcadiaLog;
import models.Auditoria;
import models.CampoSubbase;
import models.ContactoEmpresa;
import models.Organizacion;
import models.SubBase;
import models.TipoSubBase;
import play.data.binding.Binder;
import play.db.Model;
import play.exceptions.TemplateNotFoundException;
import play.mvc.With;
import utils.ArcadiaConstants.TIPO_ENTIDAD;
import utils.ArcadiaConstants.TIPO_PERSONA;
import utils.ColumnFilters;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import dtos.OrganizacionDto;

@With(Secure.class)
public class SubBases extends ArcadiaCRUD {

	public static void blank() throws Exception {
        ObjectType type = ObjectType.get(getControllerClass());
        notFoundIfNull(type);
        Constructor<?> constructor = type.entityClass.getDeclaredConstructor();
        constructor.setAccessible(true);
        Model object = (Model) constructor.newInstance();
        try {
        	List<TipoSubBase> tipoSubbases = TipoSubBase.all().fetch(20);
            render(type, object, tipoSubbases);
        } catch (TemplateNotFoundException e) {
            render("CRUD/blank.html", type, object);
        }
    }
	
	public static void exportar(String id) throws Exception {
		ObjectType type = ObjectType.get(getControllerClass());
		notFoundIfNull(type);
		Model object = type.findById(id);
		notFoundIfNull(object);
		
		List<OrganizacionDto> results = getExportResult(((SubBase) object).organizaciones);
		
		String sector_Filter = params.get("sector_Filter");
		String rama_Filter = params.get("rama_Filter");
		String rubro_Filter = params.get("rubro_Filter");
		String subrubro_Filter = params.get("subrubro_Filter");
		String tratamiento_Filter = params.get("tratamiento_Filter");
		String ejecutivoNivel1_Filter = params.get("ejecutivoNivel1_Filter");
		String ejecutivoNivel2_Filter = params.get("ejecutivoNivel2_Filter");
		String ejecutivoNivel3_Filter = params.get("ejecutivoNivel3_Filter");
		String domicilioFilter = params.get("domicilio_Filter");
		String piso_Filter = params.get("piso_Filter");
		String oficina_Filter = params.get("oficina_Filter");
		String localidad_Filter = params.get("localidad_Filter");
		String web_Filter = params.get("web_Filter");
		String mail_Filter = params.get("mail_Filter");
		String telefono_Filter = params.get("telefono_Filter");
		String celular_Filter = params.get("celular_Filter");
		String fax_Filter = params.get("fax_Filter");
		String observaciones_Filter = params.get("observaciones_Filter");
		
		String temporalName = String.valueOf(System.currentTimeMillis());
		File file;
		try {
			Auditoria auditoria = new Auditoria();
			auditoria.descripcion = "Se exporta la sub-base: ".concat(((SubBase)object).nombre);
			auditoria.user = Security.getConnected();
			auditoria.fecha = new Date();
			auditoria.subbase = (SubBase)object;
			auditoria.registros = results.size();
			auditoria._save();
			ColumnFilters filters = new ColumnFilters();
			filters.EMPRESA_REPARTICION_TITLE = true;
			filters.NOMBRE_TITLE= true;
			filters.APELLIDO_TITLE = true;
			filters.MARCA_COMERCIAL_TITLE = true;
			
			
			filters.SECTOR_TITLE= sector_Filter.equals("true");
			filters.RAMA_TITLE= rama_Filter.equals("true");
			filters.RUBRO_TITLE= rubro_Filter.equals("true");
			filters.SUBRUBRO_TITLE= subrubro_Filter.equals("true");
			filters.TRATAMIENTO_TITLE= tratamiento_Filter.equals("true");
			filters.EJECUTIVO_NIVEL1_TITLE= ejecutivoNivel1_Filter.equals("true");
			filters.EJECUTIVO_NIVEL2_TITLE= ejecutivoNivel2_Filter.equals("true");
			filters.EJECUTIVO_NIVEL3_TITLE= ejecutivoNivel3_Filter.equals("true");
			filters.DOMICILIO_TITLE= domicilioFilter.equals("true");
			filters.PISO_TITLE= piso_Filter.equals("true");
			filters.OFICINA_TITLE= oficina_Filter.equals("true");
			filters.LOCALIDAD_TITLE= localidad_Filter.equals("true");
			filters.WEB_TITLE= web_Filter.equals("true");
			filters.MAIL_1_TITLE= mail_Filter.equals("true");
			filters.MAIL_2_TITLE= mail_Filter.equals("true");
			filters.TELEFONO_1_TITLE= telefono_Filter.equals("true");
			filters.TELEFONO_2_TITLE= telefono_Filter.equals("true");
			filters.MOVIL_TITLE= celular_Filter.equals("true");
			filters.FAX_TITLE= fax_Filter.equals("true");
			filters.OBSERVACIONES_TITLE= observaciones_Filter.equals("true");			
			file = XLSExportHelper.write(temporalName, results, filters);
			String name = "subbase_".concat(((SubBase)object).nombre).concat(".xls");
			renderBinary(file, name);
		} catch (WriteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static List<OrganizacionDto> getExportResult(List<Organizacion> organizaciones) {
		List<OrganizacionDto> result = new ArrayList<OrganizacionDto>();
		
		for(Organizacion organizacion : organizaciones) {
			try {
				
				OrganizacionDto organizacionDto = new OrganizacionDto();
				BeanUtils.copyProperties(organizacionDto, organizacion);
				organizacionDto.contacto = "";
				organizacionDto.ejecutivoNivel1 = organizacion.arcadianos.size() > 0 ? organizacion.arcadianos.get(0).toString() : ""; 
				organizacionDto.ejecutivoNivel2 = organizacion.arcadianos.size() > 1 ? organizacion.arcadianos.get(1).toString() : ""; 
				organizacionDto.ejecutivoNivel3 = organizacion.arcadianos.size() > 2 ? organizacion.arcadianos.get(2).toString() : ""; 
				result.add(organizacionDto);
				
				String contacto_filter = params.get("contacto_Filter");
				boolean contactoFilter = "true".equals(contacto_filter);
				
				if(contactoFilter) {
					List<ContactoEmpresa> contactos = Organizaciones.getContactosEmpresa(organizacion);
					
					for(ContactoEmpresa contacto : contactos) {
						organizacionDto = new OrganizacionDto();
						//BeanUtils.copyProperties(organizacionDto, organizacion);
						BeanUtils.copyProperties(organizacionDto, contacto.contacto);
						organizacionDto.razonSocial = organizacion.razonSocial;
						
						organizacionDto.contacto = contacto.contacto.toString();
						organizacionDto.ejecutivoNivel1 = organizacion.arcadianos.size() > 0 ? organizacion.arcadianos.get(0).toString() : ""; 
						organizacionDto.ejecutivoNivel2 = organizacion.arcadianos.size() > 1 ? organizacion.arcadianos.get(1).toString() : ""; 
						organizacionDto.ejecutivoNivel3 = organizacion.arcadianos.size() > 2 ? organizacion.arcadianos.get(2).toString() : ""; 
						result.add(organizacionDto);
					}
				}
				else {
					
				}
			} catch (Exception e) {
			}
		}
		return result;
	}

	public static void create() throws Exception {
        ObjectType type = ObjectType.get(getControllerClass());
        notFoundIfNull(type);
        Constructor<?> constructor = type.entityClass.getDeclaredConstructor();
        constructor.setAccessible(true);
        Model object = (Model) constructor.newInstance();
        Binder.bindBean(params.getRootParamNode(), "object", object);
        validation.valid(object);
        if (validation.hasErrors()) {
            renderArgs.put("error", play.i18n.Messages.get("crud.hasErrors"));
            try {
                render(request.controller.replace(".", "/") + "/blank.html", type, object);
            } catch (TemplateNotFoundException e) {
                render("CRUD/blank.html", type, object);
            }
        }
        object._save();
        
        // se guarda el log de la creación
 		ArcadiaLog log = new ArcadiaLog();
 		log.entidad = TIPO_ENTIDAD.SUBBASE;
 		log.idEntidad = new Long(object._key().toString());
 		log.fecha = new Date();
 		log.user = Security.getConnected();
 		log.descripcion = "Creación de la SUB-BASE";
 		log._save();
 		((SubBase)object).lastLogs = log;
     		
        object._save();
        flash.success(play.i18n.Messages.get("crud.created", type.modelName));
        
        redirect(request.controller + ".show", object._key());
    }
	
	public static void save(String id) throws Exception {
        ObjectType type = ObjectType.get(getControllerClass());
        notFoundIfNull(type);
        Model object = type.findById(id);
        List<CampoSubbase> campos = CampoSubbase.find("subbase=?", (SubBase)object).fetch();
        notFoundIfNull(object);
        Binder.bindBean(params.getRootParamNode(), "object", object);
        ((SubBase)object).campos = null;
 		for (CampoSubbase campo: campos){
        	String valor = params.get("campo."+campo.id);
        	campo.valor=valor;      
        	campo._save();
        	((SubBase)object).addCampo(campo);
        }
        
        validation.valid(object);
        if (validation.hasErrors()) {
            renderArgs.put("error", play.i18n.Messages.get("crud.hasErrors"));
            try {
                render(request.controller.replace(".", "/") + "/show.html", type, object);
            } catch (TemplateNotFoundException e) {
                render("CRUD/show.html", type, object);
            }
        }
        // se guarda el log de la creación
 		ArcadiaLog log = new ArcadiaLog();
 		log.entidad = TIPO_ENTIDAD.SUBBASE;
 		log.idEntidad = new Long(object._key().toString());
 		log.fecha = new Date();
 		log.user = Security.getConnected();
 		log.descripcion = "Modificación de los datos de la SUB-BASE";
 		log._save();
 		((SubBase)object).lastLogs = log;
 		
        
        object._save();
        
        
        flash.success(play.i18n.Messages.get("crud.saved", type.modelName));
        
        redirect(request.controller + ".show", object._key());
    }
	
	public static void show(String id) throws Exception {
		ObjectType type = ObjectType.get(getControllerClass());
		notFoundIfNull(type);
		Model object = type.findById(id);
		((SubBase)object).campos = CampoSubbase.find("subbase = ?", ((SubBase)object)).fetch();
		notFoundIfNull(object);

		// start organizaciones initialization
		List<Organizacion> organizaciones = Organizacion.all().fetch(30);
		// end organizaciones initialization
		List<TipoSubBase> tipoSubbases = TipoSubBase.all().fetch(20);
		try {
			List<SubBase> subbases = SubBase.findAll();
			render(type, object, organizaciones, tipoSubbases, subbases);
		} catch (TemplateNotFoundException e) {
			render("CRUD/show.html", type, object);
		}
	}
	
	public static void email(String id) throws Exception {
		ObjectType type = ObjectType.get(getControllerClass()); 
		notFoundIfNull(type);
		Model object = type.findById(id);
		notFoundIfNull(object);

		// start organizaciones initialization
		List<Organizacion> organizaciones = ((SubBase) object).organizaciones;
		String contenido = params.get("area2");
		String subject = params.get("subject");
		if (subject==null)
			subject = "";
		if (contenido!=null && !"".equals(contenido.trim())){
			Mails.welcomeEmail(Security.getConnected(), organizaciones, subject, contenido);
			flash.success("Se envió email a todas las organizaciones de la sub-base. Por ahora estamos probando, solo enviamos mail a Eugenia :)");
		} else {
			flash.clear();
		}
		// end organizaciones initialization
		try {
			render(type, object, organizaciones);
		} catch (TemplateNotFoundException e) {
			render("CRUD/show.html", type, object);
		}
	}
	
	public static void copiar(String id) throws Exception {
		ObjectType type = ObjectType.get(getControllerClass());
		notFoundIfNull(type);
		Model object = type.findById(id);
		notFoundIfNull(object);
		//Copia la subbase
		SubBase subbase = new SubBase();
		subbase.nombre = ((SubBase)object).nombre.concat("-Copia");
		subbase.descripcion = ((SubBase)object).descripcion;
		subbase.numeroEdicion = ((SubBase)object).numeroEdicion;
		subbase.fechaFinal = ((SubBase)object).fechaFinal;
		subbase.tipoSubbase = ((SubBase)object).tipoSubbase;
		for (Organizacion org: ((SubBase)object).organizaciones){
			subbase.addOrganizacion(org);			
		}
		
		
		 // se guarda el log de la creación
 		ArcadiaLog log = new ArcadiaLog();
 		log.entidad = TIPO_ENTIDAD.SUBBASE;
 		log.idEntidad = new Long(object._key().toString());
 		log.fecha = new Date();
 		log.user = Security.getConnected();
 		log.descripcion = "Creación de la SUB-BASE - a partir de la sub-base: " + ((SubBase)object).nombre;
 		log._save();
 		subbase.lastLogs = log;
 		
		subbase._save();
		
		List<CampoSubbase> campos = CampoSubbase.find("subbase=?", (SubBase)object).fetch();
		for (CampoSubbase campo: campos){
			CampoSubbase campoCopy = new CampoSubbase();
			campoCopy.nombre = campo.nombre;
			campoCopy.valor = campo.valor;
			campoCopy.subbase=subbase;
			campoCopy.save();
			subbase.addCampo(campoCopy);
		}
		
		object = subbase;
		// start organizaciones initialization
		List<Organizacion> organizaciones = Organizacion.all().fetch(30);
		// end organizaciones initialization
		List<TipoSubBase> tipoSubbases = TipoSubBase.all().fetch(20);
		try {
			List<SubBase> subbases = SubBase.findAll();
			render("Subbases/show.html", object, organizaciones, tipoSubbases, subbases);
		} catch (TemplateNotFoundException e) {
			render("CRUD/show.html", type, object);
		}
	}

	public static void agregarCondicion(String campo, String valor, String descripcion, String condicion) {
		String[] result = new String[3];
		String query = "";
		String leyenda = "";

		String cond = "";
		String ley = "";
		query = campo.trim();

		leyenda = leyenda.concat(campo);
		if ("SI".equals(condicion)) {
			ley = " es ";
			cond = "=";
		} else {
			ley = " no es ";
			cond = "!=";
		}

		leyenda = leyenda.concat(ley);
		if (descripcion != null)
			leyenda = leyenda.concat(descripcion);
		else if (valor != null)
			leyenda = leyenda.concat(valor);

		if (campo.startsWith("is")) {
			query = query.concat(cond);
			query = query.concat("true");
			leyenda = ley;
			leyenda = ley.concat(campo.substring(2));
		} else if ("persona".equals(campo)) {
			query = query.concat(cond);
			query = query.concat(String.valueOf(TIPO_PERSONA.valueOf(valor).ordinal()));
			leyenda = ley;
			leyenda = leyenda.concat("persona ");
			leyenda = leyenda.concat(valor);
		} else if ("pais".equals(campo)) {
			query = "localidad.provincia.pais.id ";
			query = query.concat(cond);
			query = query.concat(valor);
		} else if ("provincia".equals(campo)) {
			query = "localidad.provincia.id ";
			query = query.concat(cond);
			query = query.concat(valor);
		} else if ("subbase".equals(campo)) {
			leyenda = " pertenece a la subbase ";
			leyenda = leyenda.concat(descripcion);
				
			Object id = new Long(valor);
			SubBase subbase = SubBase.findById(id);
			String ids = "";
			for (Organizacion org: subbase.organizaciones){
				ids = ids.concat(org._key().toString());
				ids = ids.concat(",");
			}
			if (!"".equals(ids)){
				ids = ids.substring(0,ids.length()-1);
				ids = "(".concat(ids).concat(")");
				if ("NO".equals(condicion)) {
					leyenda = "no ".concat(leyenda);
					query = "id not in ";
				} else
					query = "id in ";
				query = query.concat(ids);
			}
					
		} else if ("localidad".equals(campo) || "origenDato".equals(campo) || "sector".equals(campo) || "rama".equals(campo) || "rubro".equals(campo) || "subrubro".equals(campo) || "intermediario".equals(campo)) {
			query = campo.concat(".id ");
			query = query.concat(cond);
			query = query.concat(valor);
		} else {
			query = "UPPER("+campo+")";
			if ("SI".equals(condicion)) {
				query = query.concat(" like '%");

			} else {
				query = query.concat(" not like '%");
			}

			query = query.concat(valor.toUpperCase());
			query = query.concat("%'");
		}

		result[0] = "OK";
		result[1] = query;
		result[2] = leyenda;

		renderJSON(result);
	}

	public static void newSubbase(String nombre, String descripcion) {
		String[] result = new String[2];
		SubBase subbase = new SubBase();
		subbase.nombre = nombre;
		subbase.descripcion = descripcion;
		subbase._save();

		// se guarda el log de la creación
		ArcadiaLog log = new ArcadiaLog();
		log.entidad = TIPO_ENTIDAD.SUBBASE;
		log.idEntidad = new Long(subbase._key().toString());
		log.fecha = new Date();
		log.user = Security.getConnected();
		log.descripcion = "Creación de la SUB-BASE";
		log._save();
		subbase.lastLogs = log;
		subbase._save();

		result[0] = "OK";
		result[1] = subbase._key().toString();
		renderJSON(result);
	}

	public static void agregarOrganizacion(String organizacionSelected, String subbaseSelected) {
		if (agregarAuxiliar(organizacionSelected, subbaseSelected)) {
			SubBase subbase = SubBase.findById(new Long(subbaseSelected.trim()));
			redirect(request.controller + ".show", subbase._key());
		}
		else
			redirect("Admin.index");
	}

	public static void importarSubbase(String subBaseId, String subbaseSelected) {
		SubBase subbase = SubBase.findById(new Long(subBaseId.trim()));
		SubBase toImport = SubBase.findById(new Long(subbaseSelected));
		if (subbase!=null && toImport!=null){
			for (Organizacion org: toImport.organizaciones){
				if (org != null && !subbase.contains(org)) {
					subbase.addOrganizacion(org);
				}
			}
			// se guarda el log de la actualización
			ArcadiaLog log = new ArcadiaLog();
			log.entidad = TIPO_ENTIDAD.SUBBASE;
			log.idEntidad = new Long(subbase._key().toString());
			log.fecha = new Date();
			log.user = Security.getConnected();
			log.descripcion = "Se importan las organizaciones de la sub-base: " + toImport.nombre;
			log._save();
			subbase.lastLogs = log;
			subbase._save();
		}
		redirect(request.controller + ".show", subbase._key());		
	}
	
	public static void agregar(String organizacionSelected, String subbaseSelected) {
		String[] result = new String[2];
		if (agregarAuxiliar(organizacionSelected, subbaseSelected)) {
			result[0] = "OK";
			result[1] = "Las organizaciones se agregaron a la sub-base correctamente.";
		} else {
			result[0] = "ERROR";
			result[1] = "No se encuentra la sub-base que desea actualizar.";
		}
		renderJSON(result);
	}

	private static boolean agregarAuxiliar(String organizacionSelected, String subbaseSelected) {
		if (subbaseSelected != null && !"".equals(subbaseSelected.trim())) {
			SubBase subbase = SubBase.findById(new Long(subbaseSelected.trim()));
			if (subbase != null) {
				String[] selecteds = organizacionSelected.split(",");
				for (String id : selecteds) {
					if (id != null && !"".equals(id.trim())) {
						if (!"on".equals(id)){
							Organizacion organizacion = Organizacion.findById(new Long(id));						
							if (organizacion != null && !subbase.contains(organizacion)) {
								subbase.addOrganizacion(organizacion);
							}
						}
						
					}
				}
				// se guarda el log de la actualización
				ArcadiaLog log = new ArcadiaLog();
				log.entidad = TIPO_ENTIDAD.SUBBASE;
				log.idEntidad = new Long(subbase._key().toString());
				log.fecha = new Date();
				log.user = Security.getConnected();
				log.descripcion = "Se agregan organizaciones a la sub-base";
				log._save();
				subbase.lastLogs = log;
				subbase._save();
				return true;
			}
		}

		return false;
	}

	public static void search(String nombre) {
		String[] result = new String[2];
		String query = "UPPER(nombre) like '%";
		query = query.concat(nombre.toUpperCase());
		query = query.concat("%'");

		List<SubBase> subbases = SubBase.find(query).fetch();

		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
		String json = gson.toJson(subbases);
		result[0] = "OK";
		result[1] = json;
		renderJSON(result);
	}

	public static void removeOrganizacion(String organizacionSelected, String subbaseSelected) throws Exception {
		if (subbaseSelected != null && !"".equals(subbaseSelected.trim())) {
			SubBase subbase = SubBase.findById(new Long(subbaseSelected.trim()));
			Organizacion organizacion = Organizacion.findById(new Long(organizacionSelected));		
			if (subbase != null && organizacion!=null) {
				if (subbase.contains(organizacion)){
					ArcadiaLog log = new ArcadiaLog();
					log.entidad = TIPO_ENTIDAD.SUBBASE;
					log.idEntidad = new Long(subbase._key().toString());
					log.fecha = new Date();
					log.user = Security.getConnected();
					log.descripcion = "Se quita la organizacion ".concat(organizacion.toString()).concat("de la sub-base");
					log._save();
					subbase.organizaciones.remove(organizacion);
					subbase.lastLogs = log;		
					subbase._save();
				}
				
				redirect(request.controller + ".show", subbase._key());
			}
			
		} 
		
		redirect("Admin.index");
		
	}
	
	public static void newCampo(String id, String nombre, String valor){
		String[] result = new String[2];
		SubBase subbase = SubBase.findById(new Long(id));
		if (subbase != null && nombre!=null && !"".equals(nombre.trim()) && valor!=null && !"".equals(valor.trim())){
			CampoSubbase campo = new CampoSubbase();
			campo.nombre=nombre;
			campo.valor=valor;
			campo.subbase=subbase;
			campo._save();
			subbase.addCampo(campo);			
			result[0] = "OK";
		} else {
			result[0] = "ERROR";
			result[1] = "No se puede crear el nuevo campo, revise los datos ingresados";
		}
		renderJSON(result);
	}
	
	public static String getEjecutivoNivel(Organizacion organizacion, int nivel) {
		if(organizacion.arcadianos.size() >= nivel) {
			return organizacion.arcadianos.get(nivel - 1).toString();
		}
		return "-";
	}
}
